package net.guerlab.commons.time;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 时间助手类，使用标准"yyyy-MM-dd HH:mm:ss"格式和"yyyy-MM-dd"短标记格式
 *
 * @author guer
 *
 */
public final class TimeHelper {

    private static final Logger LOGGER = LoggerFactory.getLogger(TimeHelper.class);

    private static final Map<Integer, Formats> FORMATS;

    static {
        FORMATS = Arrays.stream(Formats.values()).collect(Collectors.toMap(Formats::getLength, format -> format));
    }

    private TimeHelper() {
    }

    /**
     * 日期类型对象格式化成全时间格式
     *
     * @param date
     *            日期类型对象
     * @return 全时间格式的日期内容文本
     */
    public static String format(final Date date) {
        if (date == null) {
            return null;
        }

        return DateFormatUtils.format(date, Formats.STANDARD_DATE.getFormat());
    }

    /**
     *
     * 日期类型对象格式化成只包含日期格式
     *
     * @param date
     *            日期类型对象
     * @return 只包含日期格式的日期内容文本
     */
    public static String formatDate(final LocalDateTime date) {
        if (date == null) {
            return null;
        }

        return date.format(DateTimeFormatter.ofPattern(Formats.SIMPLE_DATE.getFormat()));
    }

    /**
     * 日期类型对象格式化成全时间格式
     *
     * @param date
     *            日期类型对象
     * @return 全时间格式的日期内容文本
     */
    public static String format(final LocalDateTime date) {
        if (date == null) {
            return null;
        }

        return date.format(DateTimeFormatter.ofPattern(Formats.STANDARD_DATE.getFormat()));
    }

    /**
     *
     * 日期类型对象格式化成只包含日期格式
     *
     * @param date
     *            日期类型对象
     * @return 只包含日期格式的日期内容文本
     */
    public static String formatDate(final Date date) {
        if (date == null) {
            return null;
        }

        return DateFormatUtils.format(date, Formats.SIMPLE_DATE.getFormat());
    }

    /**
     * 通过时间字符串解析生成日期对象
     *
     * @param string
     *            时间字符串
     * @return 日期对象
     */
    public static Date parse(final String string) {
        if (StringUtils.isBlank(string)) {
            return null;
        }

        String text = string.trim();

        Date date = numberParse(text);

        if (date != null) {
            return date;
        }

        return textParase(text);
    }

    private static Date numberParse(final String text) {
        try {
            long timestamp = Long.parseLong(text);
            return new Date(timestamp);
        } catch (Exception e) {
            LOGGER.trace(e.getMessage(), e);
        }

        return null;
    }

    private static Date textParase(final String text) {
        try {
            Formats format = FORMATS.get(text.length());

            if (format == null) {
                return null;
            }

            return DateUtils.parseDate(text.replace('T', ' ').replace('Z', ' '), format.getFormat());
        } catch (Exception e) {
            LOGGER.debug(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 通过时间字符串解析生成日期对象
     *
     * @param string
     *            时间字符串
     * @return 日期时间对象
     */
    public static LocalDateTime parseLocalDateTime(final String string) {
        Date date = parse(string);

        if (date == null) {
            return null;
        }

        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    /**
     * 判断2个时间对象是否为同一天
     *
     * @param date1
     *            待判断时间对象1
     * @param date2
     *            待判断时间对象2
     * @return 是否为同一天
     */
    public static boolean isSameDate(final Date date1, final Date date2) {
        if (date1 == null || date2 == null) {
            return false;
        }

        return DateUtils.isSameDay(date1, date2);
    }
}
